Tuning Procedural Code

Procedural code, such as PL/SQL, is often a fallback position for running SQLs that are too complex to code in a single statement.

The typical model for such a module would be:

Generally speaking, a single SQL can be made to run more efficiently than the equivalent PL/SQL routine that loops through a cursor. However this should not be seen as a challenge to write huge convoluted SQLs that are impossible to maintain.

Do you have a cursor within a cursor? Or a SELECT INTO within a cursor? The single greatest cause of inefficient procedural code of the type above is when SQL is performed inside the cursor loop. Prior to v9i and the introduction of bulk binding and the FORALL statement, it was necessary to perform INSERTs, UPDATEs, and DELETEs inside a cursor loop - this was a necessary evil. All cursors and SQL statements are equivalent to performing a Nested Loops join (except less efficient). For cursors looping through a large number of rows, this can have terrible consequences.

The first thing you should do is remove as many SQLs from inside the loop as possible by joining tables into the main cursor. For simple lookups with equals joins this should be easy. Use the other techniques in this guide to re-tune the main cursor if necessary. What remains should be SQL statements inside the loop that seem impossible to merge into the main cursor.

Below are a few tricks that help avoid SQL statements within a cursor loop:

Eliminating SQL from inside cursor loops will provide the most significant time saving. For smaller but still significant improvements on high volume jobs, use BULK COLLECT to fetch cursors into Nested Tables thousands of rows at a time. This technique is detailed in the PL/SQL Users Guide and Reference. BULK COLLECT requires cursors to be explicitly declared, opened, fetched, and closed, so - for applications that use implicit cursor FOR loops - it requires a significant rewrite effort.


©Copyright 2003